home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 August: Tool Chest / Dev.CD Aug 94.toast / Tool Chest / Devices & Hardware / Apple Desktop Bus / TabletDriverƒ / TbltDrvr.a < prev   
Encoding:
Text File  |  1990-03-29  |  14.9 KB  |  355 lines  |  [TEXT/MPS ]

  1. *
  2. *    Apple Macintosh Developer Technical Support
  3. *
  4. *    Sample 'ADBS' Resource
  5. *
  6. *    TbltDrvr
  7. *
  8. *    TbltDrvr.a    -    Assembler Source
  9. *
  10. *    Copyright © 1989 Apple Computer, Inc.
  11. *    All rights reserved.
  12. *
  13. *    Versions:    1.0            03/89
  14. *
  15. *    Components:    TbltDrvr.a        March 3, 1989
  16. *
  17. *    *******************************************************************
  18. *    
  19. *    ADBS resources are loaded and executed at boot time (before
  20. *    INIT 31), and are made of two main parts, the installation/
  21. *    initialization code and the the actual driver. 
  22. *    
  23. *    In this example, the installation portion allocates memory
  24. *    in the system heap for the service routine and the "optional
  25. *    data area". It installs the driver using the ADB Mgr call SetADBInfo.
  26. *    
  27. *    Generally speaking, ADB devices are intended to be user input devices.
  28. *    The ADB Manager polls the bus every 11 milliseconds to see if a device
  29. *    has new user input data. This is accomplished by sending a talk R0 command
  30. *    to the last active device. The last active device is the last device that
  31. *    had data to send to the host. If another device has data, it can request
  32. *    a poll by sending a service request signal to the host.
  33. *    
  34. *    When a device has responded to a poll, the ADB Manager will call the driver
  35. *    to process the data. This is done a interrupt time (level 1), and
  36. *    The driver is passed the data, by getting a pointer to a pascal string
  37. *    which contains the actual data.
  38. *
  39. *    In this example, the data is in the form of a pointing device's coordinates
  40. *    and button(s) state(s). When the driver gets the data, it stores the 
  41. *    coordinate information in RawMouse and MTemp. We stuff both RawMouse and MTemp,
  42. *    because the tablet is an "absolute" device. It also checks the state of
  43. *    the button, against MBState, and if there has been a change, it will update
  44. *    MBState, and post either a mouseUp or mouseDown event, as appropriate.
  45. *
  46. *    NOTE:    This code demonstrate how to move the cursor position. This information
  47. *            is meant for input device drivers only, this technique should not
  48. *            be used by applications to move the cursor around. It's bad user
  49. *            interface, and nobody likes a bad user interface, so Just Say No!
  50. *    
  51. *    Build commands:
  52. *    
  53. *    asm TbltDrvr.a -lo TbltDrvr.a.lst -l
  54. *    link TbltDrvr.a.o -o 'MrBootDisk:System Folder:System' -rt ADBS=4 -ra =16
  55. *
  56. ***********************************************************************
  57.  
  58.                     STRING    ASIS
  59.                     PRINT    OFF
  60.                     INCLUDE 'Traps.a'
  61.                     INCLUDE 'SysEqu.a'
  62.                     PRINT    ON
  63.  
  64. **************************** Driver Offsets ***************************
  65.  
  66.                                                 ;this is the structure of the "optional data area"
  67. StartDataArea        EQU        0
  68. TabltID                EQU        StartDataArea        ;ID so Apps can find this data (should contain 'TBLT')
  69.                                                 ; this identifies the structure for this driver,
  70.                                                 ; if your structure is different, you should have 
  71.                                                 ; a different ID.
  72. R0Count                EQU        TabltID+4            ;count byte of Pascal data string returned by ADB
  73. R0Data                EQU        R0Count+1            ;data can be up to 8 bytes (but reference from R0Count
  74.                                                 ; for even address access)
  75. R1Count                EQU        R0Data+8            ;count byte of Pascal data string returned by ADB
  76.                                                 ;data can be up to 8 bytes (reference from R1Data
  77. R1Data                EQU        R1Count+1            ; for even address access)
  78. MyFlags                EQU        R1Data+8            ;hi nibble are flags, bit 7 = update system cursor (zero = yes)
  79.                                                 ;bit 6 = new R0 data, bit 5 = new R1 data (1 = new)
  80.                                                 ;lo nibble is the address we ended up at (set by installer)
  81. MyTalkR0            EQU        MyFlags+1            ;This byte used to build a talk R0 cmd byte with our new address
  82. RsrvdPtr            EQU        MyTalkR0+1            ;Back door for Apple (you never know…)
  83. Scratch                EQU        RsrvdPtr+4            ;scratch area
  84. ADBSvRt                EQU        Scratch+2            ;pointer to service routine
  85. ADBDtAr                EQU        ADBSvRt+4            ;pointer to optional data area
  86. NextjADBProc        EQU        ADBDtAr+4            ;a place to keep pointer to next guy in jADBProc chain
  87. EndDataArea            EQU        NextjADBProc+4        ;this is my end marker & how big it is
  88.  
  89. ******************************** Equates ******************************
  90.  
  91. TalkR0                EQU        $0C                    ;ADB Talk register zero (installer fills in the device address in upper nibble)
  92. TalkR1                EQU        $0D                    ;ADB Talk register one (installer fills in the device address in upper nibble)
  93. DoSysCrsr            EQU        $80                    ;mask for "update system cursor?" flag (in MyFlags)
  94. FreshR0                EQU        $40                    ;mask for new R0 data (in MyFlags)
  95. FreshR1                EQU        $20                    ;mask for new R1 data (in MyFlags)
  96. TabltType            EQU        $7F                    ;Device type of digitizing tablet
  97. ;jADBProc            EQU        $6B8                ;can't find this in MPW equ's!
  98.  
  99. ************************ Entry and installation ***********************
  100. ***
  101. ***        When the ADBS is loaded and jumped to, it comes here and branches
  102. ***        around the actual driver to the installation code.
  103. ***
  104. ***        On Entry:    A0 = Pointer to this routine
  105. ***                    D0 = ADB device address (0-15)
  106. ***                    D1 = ADB Device Type
  107. ***        
  108. ***********************************************************************
  109.  
  110. Entry    MAIN
  111.  
  112.         ALIGN 2
  113.         
  114.         bra            Installer
  115.         
  116. Entry2                                    ;this is how we enter the relocated installer
  117.         move.l        a2,a0
  118.         _DisposHandle                    ;dispose the original ADBS
  119.         move.l        #0,a2                ;clear this handle
  120.         bra            noChoice            ;now do that installation thang!
  121.         
  122. ************************ My ADB Service Routine ***********************
  123. ***
  124. ***        ADB service routine for digitizing tablets.
  125. ***        
  126. ***        This routine is called as a result of the successful completion
  127. ***        of a Talk R0 or Talk R1 command. The successful completion of Talk R0 means
  128. ***        that the tablet has either new coordinate data or a change in a
  129. ***        button state, or both. This routine is also able to handle the
  130. ***        completion of a Talk R1 command, and will update the data area
  131. ***        with R1's contents.
  132. ***        
  133. ***        On Entry:    A0 = Pointer to Device Data
  134. ***                    A1 = Pointer to this routine
  135. ***                    A2 = Pointer to optional data area
  136. ***                    D0 = ADB Command that got us called
  137. ***        
  138. ***********************************************************************
  139.  
  140. DataCount    EQU        0                            ;this is the format of the tablet data
  141. SwitchWord    EQU        DataCount+1                    ;info about switch(es) state(s)
  142. XCoord        EQU        SwitchWord+2                ;hi byte = LSB of X, lo byte = MSB of X
  143. YCoord        EQU        XCoord+2                    ;hi byte = LSB of Y, lo byte = MSB of Y
  144. ZCoord        EQU        YCoord+2                    ;hi byte = LSB of Z, lo byte = MSB of Z
  145.  
  146. SwitchMask    EQU        $80                            ;bit seven = any button down (if one)
  147.  
  148. MySrvcRt
  149.  
  150.         movem.l        a0-a3/d0-d2,-(a7)            ;save regs we will abuse
  151.         cmp.b        MyTalkR0(a2),d0
  152.         bne            DoOther                        ;if not a Talk R0, see if a Talk R1
  153.                 
  154.         move.b        MyFlags(a2),d1
  155.         andi.b        #DoSysCrsr,d1                ;see if current app wants us to update the system cursor
  156.         bne.s        NoUpdate                    ;if bit 7 set, just update data area, and check button
  157.         
  158.         move.b        YCoord(a0),MTemp+1            ;move coordinate data into cursor low mem locations
  159.         move.b        YCoord+1(a0),MTemp
  160.         move.b        XCoord(a0),MTemp+3
  161.         move.b        XCoord+1(a0),MTemp+2
  162.  
  163.          move.l         MTemp,RawMouse              ;cursor guy likes to see this twice
  164.                                                 ;to make the position absolute. If RawMouse were not
  165.                                                 ;updated, jCrsrTask would attempt to scale the move
  166.         MOVE.B        CrsrCouple,CrsrNew            ; note the change
  167. NoUpdate
  168.         lea            R0Count(a2),a3                ;set up the destination in a3, source is a0
  169.         bsr.s        MoveData                    ;go update the data area
  170.         ori.b        #FreshR0,MyFlags(a2)        ;flag to say the data is new
  171.                                                 ;  The following code with capatalized mnemonics (can
  172.                                                 ;  you say that?) is stolen from the Mac II ROM 
  173.                                                 ;  source. Thanks to the 4th floor, DA3 (or wherever
  174.                                                 ;  they are now…).
  175.         MOVEQ       #1, D0                        ; D0 holds the event (1 = mouse button down)
  176.         move.b        #$00,d2                        ;our new MBState, assume mouse down
  177.         move.b        SwitchWord+1(a0),d1            ;get switch state
  178.         andi.b        #SwitchMask,d1                ;mask for button(s) down
  179.         bne.s        Down                        ;if zero, no button down
  180.         
  181.         MOVEQ           #2, D0                        ; set D0 to 2 if mouse button is up
  182.         move.b        #$80,d2                        ;well, turns out the button's up
  183.  
  184. Down    MOVE.B      MBState, D1                    ; get copy of last state
  185.         EOR.B       D2, D1                        ; did it change?
  186.         BPL.S       MyExit                        ; if it didn't, no event
  187.  
  188. ; the mouse button changed, do debounce it , only generate event if it wasn't a bounce
  189.         MOVE.L        TICKS,D1                    ; get current system ticks
  190.         SUB.L        MBTICKS,D1                    ; and subtract ticks when the button changed
  191.         CMP.L        #1,D1                        ; was it long enough?
  192.         BLT.S        MyExit                        ; if not, don't post an event
  193.  
  194.         ADD.L        D1,RndSeed                    ; randomize our seed
  195.         MOVE.L        TICKS,MBTICKS                ; since it changed, update the ticks        
  196.  
  197.         AND.B          #$80, D2                    ; just store high bit
  198.         MOVE.B         D2, MBState                    ; also update the state
  199.  
  200. ; post the mouse button event
  201. ;**********************************************************************************************
  202.                                                 ;add call to jCrsrTask!!!!!
  203. ;**********************************************************************************************                                                
  204.         MOVE.L      D0, A0                        ; get event number where it belongs
  205.         MOVEQ        #0, D0                        ; no message
  206.         _PostEvent                                ; post the event
  207.         
  208. MyExit    movem.l        (a7)+,a0-a3/d0-d2            ;restore regs we abused
  209.         rts
  210.         
  211. DoOther
  212.  
  213.         move.b        Myflags(a2),d2
  214.         lsl.b        #4,d2                        ;move address up to hi nibble
  215.         ori.b        #TalkR1,d2                    ;now we've built a Talk R1 at our address
  216.         cmp.b        d2,d0                        ;so we can see if that's why we're here
  217.         bne.s        MyExit                        ;wasn't a Talk R0, or a Talk R1, so get out
  218.         lea            R1Count(a2),a3                ;we got a Talk R1, so point to R1 data area for move
  219.         bsr.s        MoveData                    ;go put the R1 data in the data area
  220.         ori.b        #FreshR1,MyFlags(a2)        ;flag that says data is new
  221.         bra.s        MyExit                        ;all done
  222.         
  223. MoveData                                        ;A0 points to source, A3 points to destination
  224.         movem.l        a0/a3/d0,-(a7)                ;save the regs
  225.         move.w        #$08,d0                        ;get the count (never more than 9 bytes)
  226. MD1        move.b        (a0)+,(a3)+                    ;move a byte at a time…
  227.         dbra        d0,MD1                        ;until low word of d0 = -1
  228.         movem.l        (a7)+,a0/a3/d0                ;restore the regs
  229.         rts
  230.         
  231. ************************ My ADBReInit  Procedure **********************
  232. ***
  233. ***        ADBReInit Proc for deallocating memory before re-initializing
  234. ***        the ADB Mgr
  235. ***
  236. ***        On Entry:    D0 = 0 for pre processing, 1 for post processing
  237. ***                    A0 = Pointer to this routine
  238. ***        
  239. ***********************************************************************
  240.  
  241. jProc    
  242.         cmpi.b        #1,d0
  243.         beq.s        outtaHere                    ;only do the pre-processing
  244.         move.b        d0,d2
  245.  
  246.         lea            MySrvcRtEnd,a2                ;get a pointer to the data area
  247.         lea            jADBProc,a0
  248.         move.l        NextjADBProc(a2),(a0)        ;remove ourself from the chain
  249.         move.l        NextjADBProc(a2),-(a7)        ;push address of next guy in the chain
  250.         move.l        ADBSvRt(a2),a0
  251.         _DisposPtr                                ;dispose the service routine and data area pointer
  252.         move.b        d2,d0                        ;restore d0
  253.         rts
  254.         
  255. outtaHere
  256.         lea            MySrvcRtEnd,a2                ;get a pointer to the data area
  257.         move.l        NextjADBProc(a2),-(a7)        ;push address of next guy in the chain
  258.         rts
  259.         
  260. MySrvcRtEnd                                        ;and begin optional data area
  261.  
  262. ******************************* Installer *****************************
  263. ***        On Entry:    A0 = Pointer to this routine
  264. ***                    D0 = ADB device address (0-15)
  265. ***                    D1 = ADB Device Type
  266. ***********************************************************************
  267. ******************************** Equates ******************************
  268.  
  269. DataSiz                EQU        EndDataArea-StartDataArea    ;this is how big my optional data area is
  270. RoutineSiz            EQU        MySrvcRtEnd-MySrvcRt        ;this is how big my service routine is
  271. NewPtrSiz            EQU        RoutineSiz+DataSiz
  272. jADBProcOffset        EQU        jProc-MySrvcRt                ;offset from NewPtr to my jADBProc (after blockmove)
  273. jmpOffset            EQU        entry2-entry
  274.  
  275. Installer
  276.  
  277.         movem.l        a0-a3/d0-d2,-(a7)            ;protect the virtue of the registers we use
  278.         move.b        d0,d2                        ;save device address for later
  279.         move.l        #0,a2                        ;zero our handle regs (a2 for original ADBS and a3 the new one)
  280.         move.l        #0,a3
  281.         lea            Entry,a0                    ;get a handle on the ADBS
  282.         _RecoverHandle
  283.         move.l        a0,a2                        ;keep this handle around, we need to dispose is later
  284.         cmp.b        #TabltType,d1                ;see if it's our kind of device
  285.         bne.s        exit                        ;if not, quit
  286.         
  287.         _GetHandleSize                            ;this code relocates the ADBS hi in the heap, to
  288.                                                 ;try and cause the least amount of heap fragmentation
  289.         bmi.s        exit                        ;something's wrong, let's get outta here
  290.         move.l        d0,d1                        ;we'll need the size later for BlockMove
  291.         _NewHandle    ,SYS                        ;get a new handle of our same size
  292.         bne.s        noChoice                    ;if we can't get memory, go ahead and fragment the sys heap
  293.         move.l        a0,a3                        ;remember the new handle
  294.         _MoveHHi                                ;move this new handle up in the heap (error shouldn't be possible)
  295.         _Hlock                                    ;lock it down (error shouldn't occur)
  296.         move.l        d1,d0                        ;get our size
  297.         move.l        (a0),a1                        ;set up destination ptr
  298.         move.l        (a2),a0                        ;and source
  299.         _BlockMove                                ;move entire ADBS up hi in the heap
  300.                                                 ;do this so that the NewPtr will be as low as
  301.                                                 ;possible in the heap, avoiding fragmentation due to
  302.                                                 ;ADBS being below NewPtr
  303.         adda.l        #jmpOffset,a1                ;a0 now points to Entry2 in the copy of this ADBS
  304.         jmp            (a1)                        ;now we start execution in our MoveHHi'd ADBS 
  305.         
  306. noChoice
  307.         move.l        #NewPtrSiz,d0                ;make a block for the driver and data area
  308.         _NewPtr        ,SYS,CLEAR                    ;we likes our bytes clean, we does
  309.         bne.s        exit                        ;abort if error
  310.         move.l        a0,a1                        ;set up destination for BlockMove
  311.         lea            MySrvcRt,a0                    ;and source pointer
  312.         move.l        #RoutineSiz,d0                ;and how many bytes to move
  313.         _BlockMove                                ;now move the driver into our new ptr (no errors)
  314.         move.l        a1,a0                        ;now create pointer to the data area
  315.         adda.l        #RoutineSiz,a0                ;a0 now points to area past the service routine
  316.         move.l        a0,ADBDtAr(a0)                ;keep pointer to data area in data area
  317.         move.l        a1,ADBSvRt(a0)                ;keep pointer to service routine in data area
  318.                                                 ;initialize the data area
  319.         move.l        #'TBLT',TabltID(a0)            ;set up the drivers data area
  320.         andi.b        #$0F,d2                        ;clear hi nibble of device address
  321.         or.b        d2,MyFlags(a0)                ;fill in our address for the driver's sake
  322.         move.b         d2,d0                        ;set the device addrs for our tablet (for _SetADBInfo)
  323.         lsl.b        #4,d2                        ;now move the address into the hi nibble
  324.         move.b        d2,MyTalkR0(a0)                ;Create a TalkR0 command byte for the drvr to compare with
  325.         ori.b        #TalkR0,MyTalkR0(a0)        ;now we've built a Talk R0 at our address
  326.         move.l        a0,d2                        ;keep pointer to data area for later
  327.                 
  328.         lea         ADBSvRt(a0),a0                ;set up for installing my stuff
  329.         _SetADBInfo                                ;install it!
  330.         tst.w        d0                            ;any error?
  331.         bne.s        badExit                        ;if so, abort
  332.  
  333.         move.l        d2,a0                        ;get pointer to data area back
  334.         move.l        jADBProc,NextjADBProc(a0)    ;get the next guy's address
  335.         lea            jADBProcOffset(a1),a0        ;set up the jADBProc for _ADBReInt (Just in case…)
  336.         move.l        a0,jADBProc                    ;all done
  337.         
  338. exit    move.l        a2,a0                        ;the handle of the original ADBS
  339.         cmpa.l        #0,a0                        ;make sure it's a real handle
  340.         beq.s        exit2
  341.         _DisposHandle                            ;nuke it!
  342.  
  343. exit2    move.l        a3,a0                        ;enter here with handle to dispose in a3
  344.         cmpa.l        #0,a0                        ;if handle is nil, don't dispose
  345.         beq.s        around
  346.         _DisposHandle                            ;
  347. around    movem.l        (a7)+,a0-a3/d0-d2            ;restore the registers we use
  348.         rts                                        ;Return To Sender
  349.  
  350. badExit                                            ;error occured after allocating new ptr
  351.         move.l        a1,a0
  352.         _DisposPtr                                ;get rid of our pointer
  353.         bra.s        exit
  354.                 
  355.         END